package com.example.judge.service;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.common.core.constants.Constants;
import com.example.common.core.constants.JudgeConstants;
import com.example.common.core.domain.Result;
import com.example.common.core.enums.CodeRunStatus;
import com.example.domain.UserExeResult;
import com.example.domain.dto.JudgeSubmitDTO;
import com.example.domain.vo.UserQuestionResultVO;
import com.example.judge.domain.SandBoxExecuteResult;
import com.example.judge.domain.UserSubmit;
import com.example.judge.mapper.UserSubmitMapper;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 23050
 * @version 1.0
 * @description: 判题服务
 * @date 2025/5/2 18:44
 */
@Service
public class JudgeServiceImpl implements JudgeService{

    @Resource
    private SandboxService sandboxService;

    @Resource
    private UserSubmitMapper userSubmitMapper;

    @Override
    public UserQuestionResultVO doJudgeJavaCode(JudgeSubmitDTO judgeSubmitDTO) {
        //创建代码沙箱,并在里面执行
        SandBoxExecuteResult sandBoxExecuteResult =
                sandboxService.exeJavaCode(judgeSubmitDTO.getUserCode(),judgeSubmitDTO.getInputList());
        UserQuestionResultVO userQuestionResultVO = new UserQuestionResultVO();
        //判断运行结果
        if (sandBoxExecuteResult!=null && CodeRunStatus.SUCCEED.equals(sandBoxExecuteResult.getRunStatus())){
            //执行成功
            //比对结果
            //实际结果
            userQuestionResultVO = doJudge(judgeSubmitDTO, sandBoxExecuteResult, userQuestionResultVO);
        } else{
            //执行失败
            userQuestionResultVO.setPass(Constants.FALSE);
            if (userQuestionResultVO!=null){
                userQuestionResultVO.setExeMessage(sandBoxExecuteResult.getExeMessage());
            }else{
                userQuestionResultVO.setExeMessage(CodeRunStatus.UNKNOWN_FAILED.getMsg());
            }
            userQuestionResultVO.setScore(JudgeConstants.ERROR_SCORE);
        }
        //将执行的结果存到数据库中
        saveUserSubmit(judgeSubmitDTO, userQuestionResultVO);
        return userQuestionResultVO;
    }

    //比对运行结果
    private UserQuestionResultVO doJudge(JudgeSubmitDTO judgeSubmitDTO, SandBoxExecuteResult sandBoxExecuteResult, UserQuestionResultVO userQuestionResultVO) {
        List<String> exeOutputList = sandBoxExecuteResult.getOutputList();
        //预期结果
        List<String> outputList = judgeSubmitDTO.getOutputList();
        if (outputList.size() != exeOutputList.size()) {
            //数量上都不对
            userQuestionResultVO.setScore(JudgeConstants.ERROR_SCORE);
            userQuestionResultVO.setPass(Constants.FALSE);
            userQuestionResultVO.setExeMessage(CodeRunStatus.NOT_ALL_PASSED.getMsg());
            return userQuestionResultVO;
        }

        boolean pass = true;
        //实际运行结果列表
        List<UserExeResult> userExeResultList = new ArrayList<>();
        //值比对 判断是否完全通过
        for (int i = 0;i<outputList.size();i++){
            String output = outputList.get(i);
            String exeOutput = exeOutputList.get(i);
            String input = judgeSubmitDTO.getInputList().get(i);
            UserExeResult userExeResult = new UserExeResult();
            userExeResult.setInput(input);
            userExeResult.setInput(output);
            userExeResult.setInput(exeOutput);
            userExeResultList.add(userExeResult);
            if (!output.equals(exeOutput)){
                pass=false;
            }
        }
        //将运行结果存到返回值
        userQuestionResultVO.setUserExeResultList(userExeResultList);

        //判断结果是否全部通过
        if (!pass){
            userQuestionResultVO.setPass(Constants.FALSE);
            userQuestionResultVO.setScore(JudgeConstants.ERROR_SCORE);
            userQuestionResultVO.setExeMessage(CodeRunStatus.NOT_ALL_PASSED.getMsg());
            return userQuestionResultVO;
        }
        //判断是否超过空间限制
        if (sandBoxExecuteResult.getUseMemory()> judgeSubmitDTO.getSpaceLimit()){
            userQuestionResultVO.setPass(Constants.FALSE);
            userQuestionResultVO.setScore(JudgeConstants.ERROR_SCORE);
            userQuestionResultVO.setExeMessage(CodeRunStatus.OUT_OF_MEMORY.getMsg());
            return userQuestionResultVO;
        }
        //判断是否超过时间限制
        if (sandBoxExecuteResult.getUseTime()> judgeSubmitDTO.getTimeLimit()){
            userQuestionResultVO.setPass(Constants.FALSE);
            userQuestionResultVO.setScore(JudgeConstants.ERROR_SCORE);
            userQuestionResultVO.setExeMessage(CodeRunStatus.OUT_OF_TIME.getMsg());
            return userQuestionResultVO;
        }
        //没有上述情况，表示执行通过
        userQuestionResultVO.setPass(Constants.TRUE);
        int score = judgeSubmitDTO.getDifficulty()*JudgeConstants.DEFAULT_SCORE;
        userQuestionResultVO.setScore(score);
        return userQuestionResultVO;
    }

    //往数据库里保存运行结果
    private void saveUserSubmit(JudgeSubmitDTO judgeSubmitDTO, UserQuestionResultVO userQuestionResultVO) {
        UserSubmit userSubmit = new UserSubmit();
        BeanUtil.copyProperties(userQuestionResultVO,userSubmit);
        userSubmit.setUserId(judgeSubmitDTO.getUserId());
        userSubmit.setQuestionId(judgeSubmitDTO.getQuestionId());
        userSubmit.setExamId(judgeSubmitDTO.getExamId());
        userSubmit.setProgramType(judgeSubmitDTO.getProgramType());
        userSubmit.setUserCode(judgeSubmitDTO.getUserCode());
        //先删除数据库中的这条数据 然后重新存到数据库中
        userSubmitMapper.delete(new LambdaQueryWrapper<UserSubmit>()
                .eq(UserSubmit::getUserId, judgeSubmitDTO.getUserId())
                .eq(UserSubmit::getQuestionId, judgeSubmitDTO.getQuestionId())
                .isNull(judgeSubmitDTO.getExamId()==null,UserSubmit::getExamId)
                .eq(judgeSubmitDTO.getExamId()!=null,UserSubmit::getExamId, judgeSubmitDTO.getExamId()));
        userSubmitMapper.insert(userSubmit);
    }
}
